import is.glif.fenius.ws.draft.DraftFeniusService;
import is.glif.fenius.ws.draft.Draft;

import is.glif.fenius.ws.draft.ReservationParams;
import is.glif.fenius.ws.draft.EndpointPair;
import is.glif.fenius.ws.draft.ExplicitRoute;
import is.glif.fenius.ws.draft.EndpointParams;
import is.glif.fenius.ws.draft.CommonParams;
import is.glif.fenius.ws.draft.DomainParams;
import is.glif.fenius.ws.draft.Status;
import is.glif.fenius.ws.draft.TimeParams;

import is.glif.fenius.ws.draft.CreateReq;
import is.glif.fenius.ws.draft.CreateResp;
import is.glif.fenius.ws.draft.ListReq;
import is.glif.fenius.ws.draft.ListResp;
import is.glif.fenius.ws.draft.CancelReq;
import is.glif.fenius.ws.draft.CancelResp;

import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.namespace.QName;

import java.net.URL;

import java.util.List;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import java.util.GregorianCalendar;

public class DraftRrmTest {
    static boolean debug = true;
    // public static String apoint = "IXA1";
    // public static String zpoint = "IXB2";
    public static String apoint = "glambda.net:TOKYO";
    public static String zpoint = "glambda.net:TSUKUBA";
    public static int bw = 1000 * 1000 * 1000 * 2;

    public URL url = null;
    public QName qname = new QName("http://fenius.glif.is/ws/draft/", "draft");
    DraftFeniusService port = null;

    public DraftRrmTest(String s) 
    {
	try {
	    url = new URL(s);
	    Draft service = new Draft(url, qname);
	    port = service.getDraftFeniusServicePort();
	} catch (Exception ex) {
	    System.err.println(ex);
	}
    }
	
    public boolean create(ReservationParams p) 
    {
	if (port == null) return false;

	try {
	    if (debug) printParams("Create request", p);
	    CreateReq req = new CreateReq();
	    req.setResvParams(p);

	    CreateResp res = port.create(req);

	    ReservationParams rp = res.getResvParams();
	    if (debug) printParams("Create response", rp);
	} catch (Exception e) {
	    e.printStackTrace();
	    return false;
	}
	return true;
    }

    public boolean list() 
    {
	if (port == null) return false;

	try {
	    if (debug) printParams("List request", null);
	    ListReq req = new ListReq();

	    ListResp res = port.list(req);

	    List<ReservationParams> rps = res.getReservations();
	    if (rps == null) return false;

	    int size = rps.size();
	    ReservationParams[] rp = new ReservationParams[size];
	    ReservationParams[] rpp = rps.toArray(rp);
	    for (int i = 0; i < size; i++) {
		if (debug) printParams("List response", rpp[i]);
	    }
	} catch (Exception e) {
	    e.printStackTrace();
	    return false;
	}
	return true;
    }

    public boolean cancel(String id)
    {
	if (port == null) return false;

	try {
	    if (debug) printParams("Cancel request", null);

	    CancelReq req = new CancelReq();
	    req.setReservationId(id);
	    req.setUserName("fenius-user");
	    req.setUserGroup("fenius-group");

	    CancelResp res = port.cancel(req);

	    Status status = res.getStatus();
	    System.err.println("Cancel result = " + status.toString());
	} catch (Exception e) {
	    e.printStackTrace();
	    return false;
	}
	return true;
    }

    private void printParams(String m, ReservationParams p)
    {
	String s = m + ":\n";
	if (p != null) {
	    m += "\t" + p.getReservationId() 
		+ "::" + p.getEndpoints().getA()
		+ "->" + p.getEndpoints().getZ()
		+ ":" + p.getEndtoendParams().getStatus().toString();

	    XMLGregorianCalendar c = 
		p.getEndtoendParams().getTimeParams().getScheduledStartTime();
	    m += ", From " + c.getYear() + "/" + c.getMonth() + "/" + c.getDay();
	    m += " " + c.getHour() + ":" + c.getMinute() + ":" + c.getSecond();

	    c = p.getEndtoendParams().getTimeParams().getScheduledEndTime();
	    m += ", To " /* + c.getYear() + "/" + c.getMonth() + "/" + c.getDay() */;
	    m += " " + c.getHour() + ":" + c.getMinute() + ":" + c.getSecond();

	    m += ", BW=" + p.getEndtoendParams().getBandwidth();
	}
	System.out.println(m);
    }

    static public ReservationParams createParams() 
    {
	Calendar startTime = Calendar.getInstance();
	startTime.setTime(new Date());
	startTime.set(Calendar.MILLISECOND, 0);
	startTime.add(Calendar.MINUTE, 1);
	Calendar endTime = (Calendar) startTime.clone();
	endTime.add(Calendar.MINUTE, 2);

	GregorianCalendar startgc = (GregorianCalendar) GregorianCalendar.getInstance();
	Date startDate = startTime.getTime();
	startgc.setTime(startDate);
	GregorianCalendar endgc = (GregorianCalendar) GregorianCalendar.getInstance();
	Date endDate = endTime.getTime();
	endgc.setTime(endDate);

	DatatypeFactory df = null;
	try {
	     df = DatatypeFactory.newInstance();
	} catch (javax.xml.datatype.DatatypeConfigurationException e) {
	    e.printStackTrace();
	    return null;
	}
	XMLGregorianCalendar startxgc = df.newXMLGregorianCalendar(startgc);
	XMLGregorianCalendar endxgc = df.newXMLGregorianCalendar(endgc);
;
	ReservationParams p = new ReservationParams();
	p.setUserName("fenius-user");
	p.setUserGroup("fenius-group");
	p.setReservationId("TEST");

	EndpointPair ep = new EndpointPair();
	ep.setA(apoint);
	ep.setZ(zpoint);
	p.setEndpoints(ep);

	/* if you want to set ExplicitRoute, use ep.add(ExplicitRoute). */
	{
	    List<ExplicitRoute> er = p.getExplicitRoute();
	}

	/* if you want to set EndpointParams, use ep.add(EndpointParams). */
	{
	    List<EndpointParams> epl = p.getEndpointParamsList();
	}

	/* set CommonParams(bandwidth, status, TimeParams) */
	{
	    CommonParams cp = new CommonParams();
	    cp.setBandwidth(bw);
	    cp.setStatus(Status.REQUESTING);

	    TimeParams tp = new TimeParams();
	    tp.setScheduledStartTime(startxgc);
	    tp.setScheduledEndTime(endxgc);
	    cp.setTimeParams(tp);
	    
	    p.setEndtoendParams(cp);
	}

	/* if you want to set EndpointParams, use dp.add(EndpointParams). */
	{
	    List<DomainParams> dp = p.getDomainParams();
	}

	return p;
    }

    public static void main(String[] args) {
	String timezone = "UTC";
	// String timezone = "Asia/Tokyo";
	TimeZone.setDefault(TimeZone.getTimeZone(timezone));

	DraftRrmTest[] tr = new DraftRrmTest[4];
	/* glambda */
	tr[0] = new DraftRrmTest("http://163.220.30.149:8081/DraftFeniusService?wsdl");
	/* startap */
	tr[1] = new DraftRrmTest("http://163.220.30.149:8082/DraftFeniusService?wsdl");
	/* kreonet */
	tr[2] = new DraftRrmTest("http://163.220.30.149:8083/DraftFeniusService?wsdl");
	/* phosphorus */
	tr[3] = new DraftRrmTest("http://163.220.30.149:8084/DraftFeniusService?wsdl");

	if (args != null && args.length != 0 &&
	    args[0].equals("create1")) {
	    ReservationParams p = createParams();
	    p.setReservationId("R-111");
	    p.getEndpoints().setA("g-lambda.net:TOKYO");
	    p.getEndpoints().setZ("g-lambda.net:TSUKUBA");
	    tr[0].create(p);

	    p.getEndpoints().setA("startap.net:e1200:te1/0");
	    p.getEndpoints().setZ("startap.net:e1200:te1/2");
	    tr[1].create(p);

	    p.getEndpoints().setA("ist-phosphorus.eu:xxxx");
	    p.getEndpoints().setZ("ist-phosphorus.eu:zzzz");
	    tr[3].create(p);
	} else if (args[0].equals("create2")) {
	    ReservationParams p = createParams();
	    p.setReservationId("R-222");
	    p.getEndpoints().setA("kreonet.re.kr:xxxx");
	    p.getEndpoints().setZ("kreonet.re.kr:aaaa");
	    tr[2].create(p);

	    p.getEndpoints().setA("startap.net:e1200:te1/1");
	    p.getEndpoints().setZ("startap.net:e1200:te1/2");
	    tr[1].create(p);

	    p.getEndpoints().setA("ist-phosphorus.eu:xxxx");
	    p.getEndpoints().setZ("ist-phosphorus.eu:zzzz");
	    tr[3].create(p);
	} else if (args != null && args.length != 0 &&
		   args[0].equals("list")) {
	    tr[0].list();
	    tr[1].list();
	    tr[2].list();
	    tr[3].list();
	} else if (args != null && args.length != 0 &&
		   args[0].equals("cancel") && args[1] != null ) {
	    // tr[0].cancel(args[1]);
	} else {
	    String s = "Test create | list | cancel id \n" +
		"\t create1:     create reservation for jp-us-eu\n" +
		"\t create2:     create reservation for kr-us-eu\n" +
		"\t list:        list reservation\n" +
		"\t cancel id:   not supported:cancel reservation which has id \n";
	    System.err.println(s);
	}
    }
}